#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "linklist.h"

/**
  * @brief  图书登记函数
  * @param  id char类型指针，图书的书号
  * @param  name char类型指针，图书的书名
  * @param  price float类型指针，图书的价格
  * @retval 判断是否登记完毕的标志  -->  LOGGED 登记结束   LOGGING  继续登记
  */
int BookLog(char* id, char* name, float* price)
{
	scanf_s("%19s %49s %f", id, 20, name, 50, price); //设置scanf缓冲区大小，传递预定义的长度
	if ((strcmp(id, "0") == 0) && (strcmp(name, "0") == 0) && (*(price) == 0))
	{
		return LOGGED;  
	}
	else
		return LOGGING;  
}

/**
  * @brief  图书信息表创建（链表）
  * @param  input  传递进来的Book_t的数组
  * @param  count  int类型的指针，统计登记的书的数目
  * @retval 返回头节点地址
  */
Book_t* Book_Create(Book_t * input,int* count)
{
	Book_t* Head = (Book_t*)malloc(sizeof(Book_t));
	Book_t* ptail = Head;
	Book_t* current;
	while (BookLog(input->id, input->name, &(input->price)) == LOGGING)
	{
		(*count)++;
		current = (Book_t*)malloc(sizeof(Book_t));
		ptail->next = current;
		ptail = ptail->next;
		strcpy(current->id, input->id); // 使用strcpy复制字符串
		strcpy(current->name, input->name);
		current->price = input->price;
	}
	ptail->next = NULL; //将最后一个节点指向空
	return Head;
}


/**
  * @brief  图书信息表的遍历访问
  * @param  Head  头节点
  * @param  BookNum  int类型的指针，书的数目
  * @retval 无
  */
void Book_View(Book_t* Head, int* BookNum)
{
	printf("%d\n",*BookNum);
	Book_t* current = Head;
	while (current->next != NULL)
	{
		current = current->next;
		printf("%s %s %.2f\n", current->id, current->name, current->price);
	}
}


/**
  * @brief  图书信息表的平均价格计算以及价格修改
  * @param  Head  头节点
  * @param  BookNum  int类型的指针，书的数目
  * @param  void类型的回调函数指针
  * @retval 无
  */
void Book_Change(Book_t* Head, int* BookNum,void (*View)(Book_t*, int*))
{
	Book_t* current = Head;
	float price_average = 0;
	while (current->next != NULL)
	{
		current = current->next;
		price_average = price_average + current->price;
	}
	current = Head;
	price_average = price_average / (*BookNum); //计算平均价格
	while (current->next != NULL)
	{
		current = current->next;
		if (current->price < price_average)  //价低加价1.2倍
		{
			current->price = current->price * (1.2);
		}
		else  //价高加价1.1倍
		{
			current->price = current->price * (1.1);
		}
	}
	printf("%.2f\n", price_average);
	View(Head, BookNum);  //调用回调函数指针，打印改动后的链表数据
}


/**
  * @brief  图书信息表的最贵图书的查找
  * @param  Head  头节点
  * @retval 无
  */
void Book_Find(Book_t* Head)
{
	int i = 0;
	int k = 1;
	Book_t* current = Head;
	Book_t* expensive[50] = { NULL };  //定义一个Book_t类型的指针数组，用于指向相同最贵价格的图书，数组元素个数为最大存入图书数目
	expensive[0] = Head;
	current = current->next;
	expensive[0] = expensive[0]->next;
	while (current->next != NULL)  //寻找最贵图书的思路类似排序问题
	{
		current = current->next;
		if (current->price > expensive[i]->price)
		{
			expensive[i] = current;  //expensive数组的第一个元素始终指向当前最贵图书
			if (expensive[k - 1] != NULL && (k >= 2)) //如果找到了比之前找到的相同价格的图书还要更贵的图书，就需要将之前expensive数组除首元素以外的元素全部指向空
			{
				do
				{
					expensive[k - 1] = NULL;
				} while ((k - 1)!= 1); //因为k - 1肯定是大于1的数，那么就先do后再判断循环
			}
			k = 1;
		}
		else if (current->price == expensive[i]->price)  //如果找到和第一次找到的最贵图书相同价格的书，就让数组后续元素指向这些书
		{
			expensive[k] = current;
			k++;
		}
	}
	printf("%d\n",k);
	for(i = 0;i < k;i++)
	{
		printf("%s %s %.2f\n", expensive[i]->id, expensive[i]->name, expensive[i]->price);
	}
}


/**
  * @brief  图书信息表的新图书的入库
  * @param  Head  头节点
  * @param  BookNum  int类型的指针，书的数目
  * @retval 插入是否成功  -->  FAIL 失败   SUCCESS  成功
  */
int Book_Insert(Book_t* Head, int* BookNum)
{
	int location = 0;
	int count = 1;
	char* id = (char*)malloc(sizeof(char));
	char* name = (char*)malloc(sizeof(char));
	float* price = (float*)malloc(sizeof(float)); //定义要插入的书的数据

	Book_t* current = Head;
	Book_t* prev = NULL;
	scanf_s("%d",&location);
	scanf_s("%19s %49s %f", id, 20, name, 50, price);
	if (location > *BookNum)
	{
		return FAIL;
	}
	else
	{
		while (count < location)
		{
			count++;
			current = current->next;
		}
		prev = current->next;
		current->next = (Book_t*)malloc(sizeof(Book_t));
		current = current->next;
		strcpy(current->id, id); // 使用strcpy复制字符串
		strcpy(current->name, name);
		current->price = *price;
		current->next = prev;
		(*BookNum)++;
		return SUCCESS;
	}
}


/**
  * @brief  图书信息表的旧图书的出库
  * @param  Head  头节点
  * @param  BookNum  int类型的指针，书的数目
  * @retval 出库是否成功  -->  FAIL 失败   SUCCESS  成功
  */
int Book_Delete(Book_t* Head, int* BookNum)
{
	int location = 0;
	int count = 1;

	Book_t* current = Head;
	Book_t* prev = NULL;

	scanf_s("%d", &location);
	if (location > *BookNum)
	{
		return FAIL;
	}
	else
	{
		while (count < location)
		{
			count++;
			current = current->next;
		}
		prev = current->next;
		prev = prev->next;
		current->next = prev;
		(*BookNum)--;
		return SUCCESS;
	}
}


/**
  * @brief  图书信息表的图书去重
  * @param  Head  头节点
  * @param  BookNum  int类型的指针，书的数目
  * @retval 无
  */
void Book_Derepeate(Book_t* Head, int* BookNum)
{
	int i = 0;
	Book_t* current = Head;
	Book_t* ptr = NULL;
	Book_t* prev = NULL;       //指向current的上一级，以便在current指向的空间需要被去除时及时指向current下一位
	Book_t* derepeate = NULL;  //定义去重的指针，以便在去重后释放其指向的空间
	ptr = current->next;

	while (ptr->next != NULL)   //类似冒泡排序，从第一个开始依次向后比较
	{
		prev = ptr;
		current = ptr->next;
		while (prev->next != NULL)  
		{
			if (strcmp(ptr->id, current->id) == 0) //释放空间删除节点
			{
				derepeate = current;
				prev->next = current->next;
				current = current->next;
				free(derepeate);  
				(*BookNum)--;
			}
			else
			{
				current = current->next;
				prev = prev->next;
			}
		}
		ptr = ptr->next;  //比较下一个元素是否有查重
	}
}
